﻿// Copyright (c) 2014 Morten Bakkedal
// This code is published under the MIT License.

using System;
using System.Collections.Generic;

namespace FuncLib.DualFunctions.Compilation
{
	internal class StorageAllocator
	{
		private LinkedList<Storage> allocation;
		private int maxStorage;

		public StorageAllocator()
		{
			allocation = new LinkedList<Storage>();
			maxStorage = 0;
		}

		public Storage Allocate(int length)
		{
			if (allocation.Count == 0)
			{
				Storage storage3 = new Storage(0, length);
				allocation.AddLast(storage3);
				maxStorage = Math.Max(maxStorage, storage3.Index + storage3.Length);
				return storage3;
			}

			// Try reusing ...
			int prevIndex = 0;
			for (LinkedListNode<Storage> storageNode = allocation.First; storageNode != null; storageNode = storageNode.Next)
			{
				Storage storage = storageNode.Value;
				if (storage.Index - prevIndex >= length)
				{
					Storage storage3 = new Storage(prevIndex, length);
					allocation.AddBefore(storageNode, storage3);
					maxStorage = Math.Max(maxStorage, storage3.Index + storage3.Length);

					return storage3;
				}
				prevIndex = storage.Index + storage.Length;
			}

			Storage storage2 = new Storage(allocation.Last.Value.Index + allocation.Last.Value.Length, length);
			allocation.AddLast(storage2);
			maxStorage = Math.Max(maxStorage, storage2.Index + storage2.Length);

			// FIXME cleaner...

			return storage2;
		}

		public void Free(Storage storage)
		{
			//storage.Invalidate();
			allocation.Remove(storage);
		}

		public int MaxStorage
		{
			get
			{
				return maxStorage;
			}
		}
	}
}
